package cn.tpshion.devops.node;

import cn.hutool.core.util.IdUtil;
import cn.tpshion.devops.common.constant.RedisKey;
import cn.tpshion.devops.common.enums.NodeType;
import cn.tpshion.devops.common.constant.NodeConstant;
import cn.tpshion.devops.domain.entity.NodeData;
import cn.tpshion.devops.domain.entity.SSHSecretData;
import cn.tpshion.devops.domain.entity.SecretData;
import cn.tpshion.devops.handle.SSHHandle;
import cn.tpshion.devops.node.data.SSHData;
import cn.tpshion.devops.node.support.NodeContext;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class SSHNode extends Node<SSHData> {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public NodeType nodeType() {
        return NodeType.SSH;
    }

    @Override
    public void handle(NodeContext nodeContext) throws Exception {
        log.info("SSHNode nodeContext:{}", nodeContext);
        Map<String, Object> contextData = nodeContext.getData();
        String workspace = contextData.get(NodeConstant.WORKSPACE).toString();
        SSHData data = getData(nodeContext);
        log.info("SSHNode data:{}", data);

        try (SSHHandle sshHandle = new SSHHandle(data, sseHandle, nodeContext)){
            String batchCommand = getBatchCommand(sshHandle, data.getCommand(), contextData);
            if(StringUtils.hasText(batchCommand)){
                sshHandle.exec(batchCommand);
            }

            // 处理单例命令
            if(StringUtils.hasText(data.getSingleCommand())){
                List<String> list = sshHandle.handleCommandStr(data.getSingleCommand());
                if(!ObjectUtils.isEmpty(list)){
                    for (String command : list) {
                        if(command.contains("#uuid#")){
                            command = command.replaceAll("#uuid#", IdUtil.fastUUID());
                        }
                        if(command.contains("#workspace#")){
                            command = command.replaceAll("#workspace#", workspace);
                        }
                        sshHandle.exec(command);
                    }
                }
            }
        }
    }

    private String getBatchCommand(SSHHandle sshHandle, String command, Map<String, Object> contextData){
        String workspace = contextData.get(NodeConstant.WORKSPACE).toString();
        if(!StringUtils.hasText(command)){
            return null;
        }

        List<String> list = sshHandle.handleCommandStr(command);
        if(ObjectUtils.isEmpty(list)){
            return null;
        }

        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            String item = list.get(i);
            if(item.contains("#uuid#")){
                item = item.replaceAll("#uuid#", IdUtil.fastUUID());
            }
            if(item.contains("#workspace#")){
                item = item.replaceAll("#workspace#", workspace);
            }
            builder.append(i == 0 ? item : " && " + item);
        }
        return builder.toString();
    }

    @Override
    protected SSHData getData(NodeContext nodeContext) {
        NodeData nodeData = nodeContext.getNodeData();
        SSHData data = JSON.parseObject(JSON.toJSONString(nodeData.getData()), SSHData.class);

        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        String value = hash.get(RedisKey.SECRET, data.getSecretName());
        SecretData secretData = JSON.parseObject(value, SecretData.class);

        SSHSecretData sshSecretData = JSON.parseObject(JSON.toJSONString(secretData.getData()), SSHSecretData.class);
        data.setHost(sshSecretData.getHost());
        data.setUsername(sshSecretData.getUsername());
        data.setPassword(sshSecretData.getPassword());
        data.setPort(sshSecretData.getPort());
        return data;
    }
}
